#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

#ifdef WIN32
#include <windows.h>
#endif

#include <mbwc.h>

int mbwc_to_mbs(char *desc, const wchar_t *src, int n)
{
#ifdef WIN32
    return WideCharToMultiByte(CP_ACP, 0,
                               src, -1, desc, n, NULL, NULL);
#else
    return wcstombs(desc, src, n);
#endif
}

int mbwc_to_wcs(wchar_t *desc, const char *src, int n)
{
#ifdef WIN32
    return MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
                               src, -1, desc, n);
#else
    return mbstowcs(desc, src, n);
#endif
}

int mbwc_to_mbs(char **desc, const wchar_t *src)
{
    const wchar_t *tmp;
    int            len;

    tmp = src;
    len = 0;
    while (*tmp) {
        ++len;
        ++tmp;
    }

    *desc = NULL;

    if (len == 0)
        return 0;

    int n = len * 4;
    for (;;) {
        char *buf = (char *) malloc (n);
        int r = mbwc_to_mbs(buf, src, n);

        if (r > 0 && r < n) {
            *desc = buf;
            return r;
        }

        free(buf);

        if (r <= 0)
            break;

        // make the buffer larger, re-trying
        n *= 2;
    }

    return -1;
}

int mbwc_to_wcs(wchar_t **desc, const char *src)
{
    int len;

    len = strlen (src);

    *desc = NULL;

    if (len == 0)
        return 0;

    int n = len * 2;
    for (;;) {
        wchar_t *buf = (wchar_t *) malloc (n * 2);
        int r = mbwc_to_wcs(buf, src, n);

        if (r > 0 && r < n) {
            *desc = buf;
            return r;
        }

        free(buf);

        if (r <= 0)
            break;

        n *= 2;
    }

    return -1;
}
